package org.duang.db.mongo.parser;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.bson.types.ObjectId;
import org.duang.db.IdEntity;
import org.duang.db.annotation.Id;
import org.duang.db.annotation.Vo;
import org.duang.db.annotation.VoColl;
import org.duang.db.mongo.parser.encode.Encoder;
import org.duang.db.mongo.parser.encode.PropertyEncoder;
import org.duang.db.mongo.parser.encode.VoCollEncoder;
import org.duang.db.mongo.parser.encode.VoEncoder;
import org.duang.kit.ClassKit;
import org.duang.kit.DataType;
import org.duang.kit.ToolsKit;
import org.duang.kit.UrlKit;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;

/**
 * Entity Convetor DBObject Factory
 * @author laotang
 *
 */
public class EncodeConvetor {
	
	public final static String ID_FIELD = "id";
	
	public static DBObject convetor(Object obj) {
		if(ToolsKit.isEmpty(obj)){
			throw new NullPointerException("Entity Convetor DBObject Fail: " + obj.getClass().getCanonicalName() + " is null!");
		}
		
		Field[] fields = ClassKit.getFields(obj.getClass());
		DBObject dbo = new BasicDBObject();
		if(ToolsKit.isNotEmpty(fields)){
			for (int i = 0; i < fields.length; i++) {
				Field field = fields[i];
				Encoder encoder = parser(obj, field);
//				if(ToolsUtil.isNotEmpty(encoder) && !encoder.isNull()){
				if(!encoder.isNull() && !encoder.isTran()){		//不为null且没有Tran注解
					if(ID_FIELD.equalsIgnoreCase(encoder.getFieldName())){
						if(encoder.getField().isAnnotationPresent(Id.class)){
							dbo.put(IdEntity.ID_FIELD, new ObjectId(encoder.getValue().toString()));
						} else {
							dbo.put(IdEntity.ID_FIELD, encoder.getValue());
						}
					} else {
//						Object safeObj = encoder.getValue();
						Object safeObj = UrlKit.removeHostSite(field, encoder);	//去掉域名字符串及将html标签字符串替换
						if( null != safeObj ){			// 为null时，不保存到库
							dbo.put(encoder.getFieldName(), safeObj);
						}
					}
				}
			}
		}
		return dbo;
	}
	
	
	
	public static Encoder parser(Object obj, Field field) {
		Encoder encoder = null;
		if( null != field.getAnnotation(Vo.class)){
			encoder = new VoEncoder(obj, field);
		} else if (null != field.getAnnotation(VoColl.class)){
			encoder = new VoCollEncoder(obj, field);
		} else {
			encoder = new PropertyEncoder(obj, field);
		}
		return encoder;
	}
	
	@SuppressWarnings("rawtypes")
	public static Object converterDBObject(Object obj){		
			if(ToolsKit.isEmpty(obj)) return null;		//如果为null或空字符串,直接退出
			Class<? extends Object> type = obj.getClass();			
			 if ( DataType.isString(type) 
						|| DataType.isInteger(type) || DataType.isIntegerObject(type)
						|| DataType.isLong(type) || DataType.isLongObject(type)
						|| DataType.isDouble(type) || DataType.isDoubleObject(type) 
						||DataType.isFloat(type) 	|| DataType.isFloatObject(type) 
						|| DataType.isShort(type) || DataType.isShortObject(type)
						|| DataType.isByte(type) || DataType.isByteObject(type)
						|| DataType.isBoolean(type) || DataType.isBooleanObject(type) 
						|| DataType.isChar(type) || DataType.isCharObject(type) 
//						|| DataType.isListType(type) || DataType.isSetType(type) 
//						|| DataType.isMapType(type) || DataType.isQueueType(type) 
						|| DataType.isDate(type) 
						|| DataType.isTimestamp(type)){
				 return obj;
			}  else  if(DataType.isListType(type) || DataType.isSetType(type) 
					|| DataType.isMapType(type) || DataType.isQueueType(type)){
				 //如果集合里的是一个集合的话，拿出集合里的泛型，再判断泛型对应的类是否有Vo或VoColl
				boolean isVo = false;
				Type[] paramTypes = ((ParameterizedType) type.getGenericSuperclass()).getActualTypeArguments();
				if(paramTypes.length == 1){
					Collection coll = (Collection)obj;
					List<DBObject> result = null;
					if(null != coll){
						result = new ArrayList<DBObject>();
						for(Iterator it = coll.iterator(); it.hasNext();){
							Object subObj = it.next();
							if(subObj.getClass().isAnnotationPresent(Vo.class) || (subObj.getClass().isAnnotationPresent(VoColl.class))) {
								if(ToolsKit.isNotEmpty(subObj)){
									isVo = true;
									result.add(EncodeConvetor.convetor(subObj));
								}
							} else break;
						}
					}
					return isVo ? result : obj;
				} else if(paramTypes.length == 2) {
					Map map = (Map)obj;
					Map result = new HashMap(map.size());
					for(Iterator<String> it = map.keySet().iterator(); it.hasNext();){
						String key = it.next();
						Object subObj = map.get(key);
						if(subObj.getClass().isAnnotationPresent(Vo.class) || (subObj.getClass().isAnnotationPresent(VoColl.class))) {
							isVo = true;
							if( null != subObj){
								result.put(key, convetor(subObj));
							} else {
								result.put(key, null);
							}
						} else break;
					}
					return isVo ? result : obj;
				}
				return obj;
			 }
			 else {
				System.out.println("##########EncodeConvetor converterDBObject Object ClassName is: " + type.getName());
				return convetor(obj);
			}
	}

}
